package etm;

import robocode.Robot;
import robocode.ScannedRobotEvent;
import robocode.HitRobotEvent;
import static robocode.util.Utils.normalRelativeAngleDegrees;
import robocode.HitByBulletEvent;
import java.awt.Color;

/**
 * Creates a robot that uses the 4 corners type of movement along with progressive targeting and
 * retaliation techniques in order to defeat opponents in a 1v1 style match. Order of corners: Upper
 * Left > Lower Right > Upper Right > Lower Left.
 * 
 * @author Edward Meyer
 * @version 1.1
 * 
 */
public class StrafeNShoot extends Robot {

  /**
   * Creates a robot that uses the 4 corners type of movement along with progressive targeting and
   * retaliation techniques in order to defeat opponents in a 1v1 style match. Order of corners:
   * Upper Left > Lower Right > Upper Right > Lower Left.
   */
  public void run() {
    
    // Custom colors for this robot
    setBodyColor(Color.white);
    setGunColor(Color.black);
    setRadarColor(Color.blue);
    setScanColor(Color.white);
    setBulletColor(Color.pink);
    
    // Get the battlefields dimensions, compensate for tanks dimensions
    double maxSizeX = getBattleFieldWidth() - 18;
    double maxSizeY = getBattleFieldHeight() - 18;

    // Keep going in the 4 corners movement throughout entire match
    while (true) {

      // Calculate angle needed to face upper left corner, and turn gun roughly at the center for
      // upper left
      turnRight(normalRelativeAngleDegrees(Math.atan((18 - getX()) / (maxSizeY - getY())) * 180
          / Math.PI - getHeading()));

      turnGunRight(normalRelativeAngleDegrees(135 - getHeading()));
      // Calculate the distance and move to upper left corner
      ahead(Math.sqrt(Math.pow(18 - getX(), 2) + Math.pow(maxSizeY - getY(), 2)));

      // Calculate the angle needed to face lower right corner, and turn gun roughly at the center
      // from lower right
      turnRight(normalRelativeAngleDegrees(Math.atan((maxSizeX - getX()) / (18 - getY())) * 180
          / Math.PI - getHeading() + 180));
      turnGunRight(normalRelativeAngleDegrees(315 - getHeading()));
      // Calculate the distance and move to upper left corner
      ahead(Math.sqrt(Math.pow(maxSizeX, 2) + Math.pow(maxSizeY, 2)));

      // Calculate the angle needed to face upper right corner, and turn gun roughly at the center
      // from upper right
      turnRight(normalRelativeAngleDegrees(Math.atan((maxSizeX - getX()) / (maxSizeY - getY()))
          * 180 / Math.PI - getHeading()));
      turnGunRight(normalRelativeAngleDegrees(0 - getHeading() - getRadarHeading() - 45));
      // Calculate the distance and move to upper right corner
      ahead(Math.sqrt(Math.pow(maxSizeX - getX(), 2) + Math.pow(maxSizeY - getY(), 2)));

      // Calculate the angle needed to face lower left corner, and turn gun roughly at the center
      // from lower left
      turnRight(normalRelativeAngleDegrees(Math.atan((18 - getX()) / (18 - getY()))
          * (180 / Math.PI) - getHeading()) - 180);
      turnGunRight(normalRelativeAngleDegrees(45 - getHeading()));
      // Calculate the distance and move to lower left corner
      ahead(Math.sqrt(Math.pow(maxSizeX, 2) + Math.pow(maxSizeY, 2)));

    }
  }

  /**
   * Once the robot sees a target, turn the gun towards it and fire with power 2.
   * 
   * @param e is the just scanned robot
   */
  public void onScannedRobot(ScannedRobotEvent e) {

    // Calculate the angle to turn the gun and fire with power 2
    double gunTurnAmt =
      normalRelativeAngleDegrees(e.getBearing() + (getHeading() - getRadarHeading()));

    turnGunRight(gunTurnAmt);
    fire(2);

  }

  /**
   * If the robot comes into contact with another, will target and fire will full power.
   * 
   * @param e is the robot that just collided
   */
  public void onHitRobot(HitRobotEvent e) {

    // Calculate degree to turn towards robot
    double gunTurnAmt =
      normalRelativeAngleDegrees(e.getBearing() + (getHeading() - getRadarHeading()));

    // Reposition gun towards target
    turnGunRight(gunTurnAmt);
    turnRight(e.getBearing());

    // Since at point-blank range, use maximum power
    fire(3);

  }

  /**
   * While moving to the corners, if the robot gets hit, will immediately retaliate with maximum
   * power.
   * 
   * @param b is the bullet that hit the robot
   */
  public void onHitByBullet(HitByBulletEvent b) {

    // Calculate degree to turn in the direction the bullet came from
    double gunTurnAmt =
      normalRelativeAngleDegrees(b.getBearing() + (getHeading() - getRadarHeading()));
    // Reposition gun towards target
    turnGunRight(gunTurnAmt);

    // When shooting at a last known heading, use maximum power.
    // May seem like a waste of energy, but will gain maximum points if bullet hits
    fire(3);
  }
}
